{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 15.10 \u7528Cython\u5305\u88c5C\u4ee3\u7801\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u60f3\u4f7f\u7528Cython\u6765\u521b\u5efa\u4e00\u4e2aPython\u6269\u5c55\u6a21\u5757\uff0c\u7528\u6765\u5305\u88c5\u67d0\u4e2a\u5df2\u5b58\u5728\u7684C\u51fd\u6570\u5e93\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f7f\u7528Cython\u6784\u5efa\u4e00\u4e2a\u6269\u5c55\u6a21\u5757\u770b\u4e0a\u53bb\u5f88\u624b\u5199\u6269\u5c55\u6709\u4e9b\u7c7b\u4f3c\uff0c\n\u56e0\u4e3a\u4f60\u9700\u8981\u521b\u5efa\u5f88\u591a\u5305\u88c5\u51fd\u6570\u3002\u4e0d\u8fc7\uff0c\u8ddf\u524d\u9762\u4e0d\u540c\u7684\u662f\uff0c\u4f60\u4e0d\u9700\u8981\u5728C\u8bed\u8a00\u4e2d\u505a\u8fd9\u4e9b\u2014\u2014\u4ee3\u7801\u770b\u4e0a\u53bb\u66f4\u50cf\u662fPython\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f5c\u4e3a\u51c6\u5907\uff0c\u5047\u8bbe\u672c\u7ae0\u4ecb\u7ecd\u90e8\u5206\u7684\u793a\u4f8b\u4ee3\u7801\u5df2\u7ecf\u88ab\u7f16\u8bd1\u5230\u67d0\u4e2a\u53eb libsample \u7684C\u51fd\u6570\u5e93\u4e2d\u4e86\u3002\n\u9996\u5148\u521b\u5efa\u4e00\u4e2a\u540d\u53eb csample.pxd \u7684\u6587\u4ef6\uff0c\u5982\u4e0b\u6240\u793a\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# csample.pxd\n#\n# Declarations of \"external\" C functions and structures\n\ncdef extern from \"sample.h\":\n    int gcd(int, int)\n    bint in_mandel(double, double, int)\n    int divide(int, int, int *)\n    double avg(double *, int) nogil\n\n    ctypedef struct Point:\n         double x\n         double y\n\n    double distance(Point *, Point *)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u4e2a\u6587\u4ef6\u5728Cython\u4e2d\u7684\u4f5c\u7528\u5c31\u8ddfC\u7684\u5934\u6587\u4ef6\u4e00\u6837\u3002\n\u521d\u59cb\u58f0\u660e cdef\u00a0 extern\u00a0 from\u00a0 \"sample.h\" \u6307\u5b9a\u4e86\u6240\u5b66\u7684C\u5934\u6587\u4ef6\u3002\n\u63a5\u4e0b\u6765\u7684\u58f0\u660e\u90fd\u662f\u6765\u81ea\u4e8e\u90a3\u4e2a\u5934\u6587\u4ef6\u3002\u6587\u4ef6\u540d\u662f csample.pxd \uff0c\u800c\u4e0d\u662f sample.pxd \u2014\u2014\u8fd9\u70b9\u5f88\u91cd\u8981\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e0b\u4e00\u6b65\uff0c\u521b\u5efa\u4e00\u4e2a\u540d\u4e3a sample.pyx \u7684\u95ee\u9898\u3002\n\u8be5\u6587\u4ef6\u4f1a\u5b9a\u4e49\u5305\u88c5\u5668\uff0c\u7528\u6765\u6865\u63a5Python\u89e3\u91ca\u5668\u5230 csample.pxd \u4e2d\u58f0\u660e\u7684C\u4ee3\u7801\u3002"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# sample.pyx\n\n# Import the low-level C declarations\ncimport csample\n\n# Import some functionality from Python and the C stdlib\nfrom cpython.pycapsule cimport *\n\nfrom libc.stdlib cimport malloc, free\n\n# Wrappers\ndef gcd(unsigned int x, unsigned int y):\n    return csample.gcd(x, y)\n\ndef in_mandel(x, y, unsigned int n):\n    return csample.in_mandel(x, y, n)\n\ndef divide(x, y):\n    cdef int rem\n    quot = csample.divide(x, y, &rem)\n    return quot, rem\n\ndef avg(double[:] a):\n    cdef:\n        int sz\n        double result\n\n    sz = a.size\n    with nogil:\n        result = csample.avg(<double *> &a[0], sz)\n    return result\n\n# Destructor for cleaning up Point objects\ncdef del_Point(object obj):\n    pt = <csample.Point *> PyCapsule_GetPointer(obj,\"Point\")\n    free(<void *> pt)\n\n# Create a Point object and return as a capsule\ndef Point(double x,double y):\n    cdef csample.Point *p\n    p = <csample.Point *> malloc(sizeof(csample.Point))\n    if p == NULL:\n        raise MemoryError(\"No memory to make a Point\")\n    p.x = x\n    p.y = y\n    return PyCapsule_New(<void *>p,\"Point\",<PyCapsule_Destructor>del_Point)\n\ndef distance(p1, p2):\n    pt1 = <csample.Point *> PyCapsule_GetPointer(p1,\"Point\")\n    pt2 = <csample.Point *> PyCapsule_GetPointer(p2,\"Point\")\n    return csample.distance(pt1,pt2)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8be5\u6587\u4ef6\u66f4\u591a\u7684\u7ec6\u8282\u90e8\u5206\u4f1a\u5728\u8ba8\u8bba\u90e8\u5206\u8be6\u7ec6\u5c55\u5f00\u3002\n\u6700\u540e\uff0c\u4e3a\u4e86\u6784\u5efa\u6269\u5c55\u6a21\u5757\uff0c\u50cf\u4e0b\u9762\u8fd9\u6837\u521b\u5efa\u4e00\u4e2a setup.py \u6587\u4ef6\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "from distutils.core import setup\nfrom distutils.extension import Extension\nfrom Cython.Distutils import build_ext\n\next_modules = [\n    Extension('sample',\n\n              ['sample.pyx'],\n              libraries=['sample'],\n              library_dirs=['.'])]\nsetup(\n  name = 'Sample extension module',\n  cmdclass = {'build_ext': build_ext},\n  ext_modules = ext_modules\n)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8981\u6784\u5efa\u6211\u4eec\u6d4b\u8bd5\u7684\u76ee\u6807\u6a21\u5757\uff0c\u50cf\u4e0b\u9762\u8fd9\u6837\u505a\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "bash % python3 setup.py build_ext --inplace\nrunning build_ext\ncythoning sample.pyx to sample.c\nbuilding 'sample' extension\ngcc -fno-strict-aliasing -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes\n -I/usr/local/include/python3.3m -c sample.c\n -o build/temp.macosx-10.6-x86_64-3.3/sample.o\ngcc -bundle -undefined dynamic_lookup build/temp.macosx-10.6-x86_64-3.3/sample.o\n  -L. -lsample -o sample.so\nbash %"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u4e00\u5207\u987a\u5229\u7684\u8bdd\uff0c\u4f60\u5e94\u8be5\u6709\u4e86\u4e00\u4e2a\u6269\u5c55\u6a21\u5757 sample.so \uff0c\u53ef\u5728\u4e0b\u9762\u4f8b\u5b50\u4e2d\u4f7f\u7528\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import sample\nsample.gcd(42,10)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "sample.in_mandel(1,1,400)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "sample.in_mandel(0,0,400)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "sample.divide(42,10)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import array\na = array.array('d',[1,2,3])\nsample.avg(a)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "p1 = sample.Point(2,3)\np2 = sample.Point(4,5)\np1"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "p2"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "sample.distance(p1,p2)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u672c\u8282\u5305\u542b\u4e86\u5f88\u591a\u524d\u9762\u6240\u8bb2\u7684\u9ad8\u7ea7\u7279\u6027\uff0c\u5305\u62ec\u6570\u7ec4\u64cd\u4f5c\u3001\u5305\u88c5\u9690\u5f62\u6307\u9488\u548c\u91ca\u653eGIL\u3002\n\u6bcf\u4e00\u90e8\u5206\u90fd\u4f1a\u9010\u4e2a\u88ab\u8bb2\u8ff0\u5230\uff0c\u4f46\u662f\u6211\u4eec\u6700\u597d\u80fd\u590d\u4e60\u4e00\u4e0b\u524d\u9762\u51e0\u5c0f\u8282\u3002\n\u5728\u9876\u5c42\uff0c\u4f7f\u7528Cython\u662f\u57fa\u4e8eC\u4e4b\u4e0a\u3002.pxd\u6587\u4ef6\u4ec5\u4ec5\u53ea\u5305\u542bC\u5b9a\u4e49\uff08\u7c7b\u4f3c.h\u6587\u4ef6\uff09\uff0c\n.pyx\u6587\u4ef6\u5305\u542b\u4e86\u5b9e\u73b0\uff08\u7c7b\u4f3c.c\u6587\u4ef6\uff09\u3002cimport \u8bed\u53e5\u88abCython\u7528\u6765\u5bfc\u5165.pxd\u6587\u4ef6\u4e2d\u7684\u5b9a\u4e49\u3002\n\u5b83\u8ddf\u4f7f\u7528\u666e\u901a\u7684\u52a0\u8f7dPython\u6a21\u5757\u7684\u5bfc\u5165\u8bed\u53e5\u662f\u4e0d\u540c\u7684\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5c3d\u7ba1 .pxd \u6587\u4ef6\u5305\u542b\u4e86\u5b9a\u4e49\uff0c\u4f46\u5b83\u4eec\u5e76\u4e0d\u662f\u7528\u6765\u81ea\u52a8\u521b\u5efa\u6269\u5c55\u4ee3\u7801\u7684\u3002\n\u56e0\u6b64\uff0c\u4f60\u8fd8\u662f\u8981\u5199\u5305\u88c5\u51fd\u6570\u3002\u4f8b\u5982\uff0c\u5c31\u7b97 csample.pxd \u6587\u4ef6\u58f0\u660e\u4e86 int gcd(int, int) \u51fd\u6570\uff0c\n\u4f60\u4ecd\u7136\u9700\u8981\u5728 sample.pyx \u4e2d\u4e3a\u5b83\u5199\u4e00\u4e2a\u5305\u88c5\u51fd\u6570\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "cimport csample\n\ndef gcd(unsigned int x, unsigned int y):\n    return csample.gcd(x,y)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5bf9\u4e8e\u7b80\u5355\u7684\u51fd\u6570\uff0c\u4f60\u5e76\u4e0d\u9700\u8981\u53bb\u505a\u592a\u591a\u7684\u65f6\u3002\nCython\u4f1a\u751f\u6210\u5305\u88c5\u4ee3\u7801\u6765\u6b63\u786e\u7684\u8f6c\u6362\u53c2\u6570\u548c\u8fd4\u56de\u503c\u3002\n\u7ed1\u5b9a\u5230\u5c5e\u6027\u4e0a\u7684C\u6570\u636e\u7c7b\u578b\u662f\u53ef\u9009\u7684\u3002\u4e0d\u8fc7\uff0c\u5982\u679c\u4f60\u5305\u542b\u4e86\u5b83\u4eec\uff0c\u4f60\u53ef\u4ee5\u53e6\u5916\u505a\u4e00\u4e9b\u9519\u8bef\u68c0\u67e5\u3002\n\u4f8b\u5982\uff0c\u5982\u679c\u6709\u4eba\u4f7f\u7528\u8d1f\u6570\u6765\u8c03\u7528\u8fd9\u4e2a\u51fd\u6570\uff0c\u4f1a\u629b\u51fa\u4e00\u4e2a\u5f02\u5e38\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "sample.gcd(-10,2)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u4f60\u60f3\u5bf9\u5305\u88c5\u51fd\u6570\u505a\u53e6\u5916\u7684\u68c0\u67e5\uff0c\u53ea\u9700\u8981\u4f7f\u7528\u53e6\u5916\u7684\u5305\u88c5\u4ee3\u7801\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "def gcd(unsigned int x, unsigned int y):\n    if x <= 0:\n        raise ValueError(\"x must be > 0\")\n    if y <= 0:\n        raise ValueError(\"y must be > 0\")\n    return csample.gcd(x,y)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728csample.pxd\u6587\u4ef6\u4e2d\u7684``in_mandel()`` \u58f0\u660e\u6709\u4e2a\u5f88\u6709\u8da3\u4f46\u662f\u6bd4\u8f83\u96be\u7406\u89e3\u7684\u5b9a\u4e49\u3002\n\u5728\u8fd9\u4e2a\u6587\u4ef6\u4e2d\uff0c\u51fd\u6570\u88ab\u58f0\u660e\u4e3a\u7136\u540e\u4e00\u4e2abint\u800c\u4e0d\u662f\u4e00\u4e2aint\u3002\n\u5b83\u4f1a\u8ba9\u51fd\u6570\u521b\u5efa\u4e00\u4e2a\u6b63\u786e\u7684Boolean\u503c\u800c\u4e0d\u662f\u7b80\u5355\u7684\u6574\u6570\u3002\n\u56e0\u6b64\uff0c\u8fd4\u56de\u503c0\u8868\u793aFalse\u800c1\u8868\u793aTrue\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728Cython\u5305\u88c5\u5668\u4e2d\uff0c\u4f60\u53ef\u4ee5\u9009\u62e9\u58f0\u660eC\u6570\u636e\u7c7b\u578b\uff0c\u4e5f\u53ef\u4ee5\u4f7f\u7528\u6240\u6709\u7684\u5e38\u89c1Python\u5bf9\u8c61\u3002\n\u5bf9\u4e8e divide() \u7684\u5305\u88c5\u5668\u5c55\u793a\u4e86\u8fd9\u6837\u4e00\u4e2a\u4f8b\u5b50\uff0c\u540c\u65f6\u8fd8\u6709\u5982\u4f55\u53bb\u5904\u7406\u4e00\u4e2a\u6307\u9488\u53c2\u6570\u3002"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "def divide(x,y):\n    cdef int rem\n    quot = csample.divide(x,y,&rem)\n    return quot, rem"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728\u8fd9\u91cc\uff0crem \u53d8\u91cf\u88ab\u663e\u793a\u7684\u58f0\u660e\u4e3a\u4e00\u4e2aC\u6574\u578b\u53d8\u91cf\u3002\n\u5f53\u5b83\u88ab\u4f20\u5165 divide() \u51fd\u6570\u7684\u65f6\u5019\uff0c&rem \u521b\u5efa\u4e00\u4e2a\u8ddfC\u4e00\u6837\u7684\u6307\u5411\u5b83\u7684\u6307\u9488\u3002\navg() \u51fd\u6570\u7684\u4ee3\u7801\u6f14\u793a\u4e86Cython\u66f4\u9ad8\u7ea7\u7684\u7279\u6027\u3002\n\u9996\u5148 def avg(double[:] a) \u58f0\u660e\u4e86 avg() \u63a5\u53d7\u4e00\u4e2a\u4e00\u7ef4\u7684\u53cc\u7cbe\u5ea6\u5185\u5b58\u89c6\u56fe\u3002\n\u6700\u60ca\u5947\u7684\u90e8\u5206\u662f\u8fd4\u56de\u7684\u7ed3\u679c\u51fd\u6570\u53ef\u4ee5\u63a5\u53d7\u4efb\u4f55\u517c\u5bb9\u7684\u6570\u7ec4\u5bf9\u8c61\uff0c\u5305\u62ec\u88abnumpy\u521b\u5efa\u7684\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import array\na = array.array('d',[1,2,3])\nimport numpy\nb = numpy.array([1., 2., 3.])\nimport sample\nsample.avg(a)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "sample.avg(b)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728\u6b64\u5305\u88c5\u5668\u4e2d\uff0ca.size0 \u548c &a[0] \u5206\u522b\u5f15\u7528\u6570\u7ec4\u5143\u7d20\u4e2a\u6570\u548c\u5e95\u5c42\u6307\u9488\u3002\n\u8bed\u6cd5 <double *> &a[0] \u6559\u4f60\u600e\u6837\u5c06\u6307\u9488\u8f6c\u6362\u4e3a\u4e0d\u540c\u7684\u7c7b\u578b\u3002\n\u524d\u63d0\u662fC\u4e2d\u7684 avg() \u63a5\u53d7\u4e00\u4e2a\u6b63\u786e\u7c7b\u578b\u7684\u6307\u9488\u3002\n\u53c2\u8003\u4e0b\u4e00\u8282\u5173\u4e8eCython\u5185\u5b58\u89c6\u56fe\u7684\u66f4\u9ad8\u7ea7\u8bb2\u8ff0\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u9664\u4e86\u5904\u7406\u901a\u5e38\u7684\u6570\u7ec4\u5916\uff0cavg() \u7684\u8fd9\u4e2a\u4f8b\u5b50\u8fd8\u5c55\u793a\u4e86\u5982\u4f55\u5904\u7406\u5168\u5c40\u89e3\u91ca\u5668\u9501\u3002\n\u8bed\u53e5 with nogil: \u58f0\u660e\u4e86\u4e00\u4e2a\u4e0d\u9700\u8981GIL\u5c31\u80fd\u6267\u884c\u7684\u4ee3\u7801\u5757\u3002\n\u5728\u8fd9\u4e2a\u5757\u4e2d\uff0c\u4e0d\u80fd\u6709\u4efb\u4f55\u7684\u666e\u901aPython\u5bf9\u8c61\u2014\u2014\u53ea\u80fd\u4f7f\u7528\u88ab\u58f0\u660e\u4e3a cdef \u7684\u5bf9\u8c61\u548c\u51fd\u6570\u3002\n\u53e6\u5916\uff0c\u5916\u90e8\u51fd\u6570\u5fc5\u987b\u73b0\u5b9e\u7684\u58f0\u660e\u5b83\u4eec\u80fd\u4e0d\u4f9d\u8d56GIL\u5c31\u80fd\u6267\u884c\u3002\n\u56e0\u6b64\uff0c\u5728csample.pxd\u6587\u4ef6\u4e2d\uff0cavg() \u88ab\u58f0\u660e\u4e3a double avg(double *, int) nogil ."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5bf9Point\u7ed3\u6784\u4f53\u7684\u5904\u7406\u662f\u4e00\u4e2a\u6311\u6218\u3002\u672c\u8282\u4f7f\u7528\u80f6\u56ca\u5bf9\u8c61\u5c06Point\u5bf9\u8c61\u5f53\u505a\u9690\u5f62\u6307\u9488\u6765\u5904\u7406\uff0c\u8fd9\u4e2a\u572815.4\u5c0f\u8282\u4ecb\u7ecd\u8fc7\u3002\n\u8981\u8fd9\u6837\u505a\u7684\u8bdd\uff0c\u5e95\u5c42Cython\u4ee3\u7801\u7a0d\u5fae\u6709\u70b9\u590d\u6742\u3002\n\u9996\u5148\uff0c\u4e0b\u9762\u7684\u5bfc\u5165\u88ab\u7528\u6765\u5f15\u5165C\u51fd\u6570\u5e93\u548cPython C API\u4e2d\u5b9a\u4e49\u7684\u51fd\u6570\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "from cpython.pycapsule cimport *\nfrom libc.stdlib cimport malloc, free"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u51fd\u6570 del_Point() \u548c Point() \u4f7f\u7528\u8fd9\u4e2a\u529f\u80fd\u6765\u521b\u5efa\u4e00\u4e2a\u80f6\u56ca\u5bf9\u8c61\uff0c\n\u5b83\u4f1a\u5305\u88c5\u4e00\u4e2a Point\u00a0 * \u6307\u9488\u3002cdef\u00a0 del_Point() \u5c06 del_Point() \u58f0\u660e\u4e3a\u4e00\u4e2a\u51fd\u6570\uff0c\n\u53ea\u80fd\u901a\u8fc7Cython\u8bbf\u95ee\uff0c\u800c\u4e0d\u80fd\u4ecePython\u4e2d\u8bbf\u95ee\u3002\n\u56e0\u6b64\uff0c\u8fd9\u4e2a\u51fd\u6570\u5bf9\u5916\u90e8\u662f\u4e0d\u53ef\u89c1\u7684\u2014\u2014\u5b83\u88ab\u7528\u6765\u5f53\u505a\u4e00\u4e2a\u56de\u8c03\u51fd\u6570\u6765\u6e05\u7406\u80f6\u56ca\u5206\u914d\u7684\u5185\u5b58\u3002\n\u51fd\u6570\u8c03\u7528\u6bd4\u5982 PyCapsule_New() \u3001PyCapsule_GetPointer()\n\u76f4\u63a5\u6765\u81eaPython C API\u5e76\u4e14\u4ee5\u540c\u6837\u7684\u65b9\u5f0f\u88ab\u4f7f\u7528\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "distance \u51fd\u6570\u4ece Point() \u521b\u5efa\u7684\u80f6\u56ca\u5bf9\u8c61\u4e2d\u63d0\u53d6\u6307\u9488\u3002\n\u8fd9\u91cc\u8981\u6ce8\u610f\u7684\u662f\u4f60\u4e0d\u9700\u8981\u62c5\u5fc3\u5f02\u5e38\u5904\u7406\u3002\n\u5982\u679c\u4e00\u4e2a\u9519\u8bef\u7684\u5bf9\u8c61\u88ab\u4f20\u8fdb\u6765\uff0cPyCapsule_GetPointer() \u4f1a\u629b\u51fa\u4e00\u4e2a\u5f02\u5e38\uff0c\n\u4f46\u662fCython\u5df2\u7ecf\u77e5\u9053\u600e\u4e48\u67e5\u627e\u5230\u5b83\uff0c\u5e76\u5c06\u5b83\u4ece distance() \u4f20\u9012\u51fa\u53bb\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5904\u7406Point\u7ed3\u6784\u4f53\u4e00\u4e2a\u7f3a\u70b9\u662f\u5b83\u7684\u5b9e\u73b0\u662f\u4e0d\u53ef\u89c1\u7684\u3002\n\u4f60\u4e0d\u80fd\u8bbf\u95ee\u4efb\u4f55\u5c5e\u6027\u6765\u67e5\u770b\u5b83\u7684\u5185\u90e8\u3002\n\u8fd9\u91cc\u6709\u53e6\u5916\u4e00\u79cd\u65b9\u6cd5\u53bb\u5305\u88c5\u5b83\uff0c\u5c31\u662f\u5b9a\u4e49\u4e00\u4e2a\u6269\u5c55\u7c7b\u578b\uff0c\u5982\u4e0b\u6240\u793a\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# sample.pyx\n\ncimport csample\nfrom libc.stdlib cimport malloc, free\n...\n\ncdef class Point:\n    cdef csample.Point *_c_point\n    def __cinit__(self, double x, double y):\n        self._c_point = <csample.Point *> malloc(sizeof(csample.Point))\n        self._c_point.x = x\n        self._c_point.y = y\n\n    def __dealloc__(self):\n        free(self._c_point)\n\n    property x:\n        def __get__(self):\n            return self._c_point.x\n        def __set__(self, value):\n            self._c_point.x = value\n\n    property y:\n        def __get__(self):\n            return self._c_point.y\n        def __set__(self, value):\n            self._c_point.y = value\n\ndef distance(Point p1, Point p2):\n    return csample.distance(p1._c_point, p2._c_point)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728\u8fd9\u91cc\uff0ccdif\u7c7b Point \u5c06Point\u58f0\u660e\u4e3a\u4e00\u4e2a\u6269\u5c55\u7c7b\u578b\u3002\n\u7c7b\u5c5e\u6027 cdef csample.Point *_c_point \u58f0\u660e\u4e86\u4e00\u4e2a\u5b9e\u4f8b\u53d8\u91cf\uff0c\n\u62e5\u6709\u4e00\u4e2a\u6307\u5411\u5e95\u5c42Point\u7ed3\u6784\u4f53\u7684\u6307\u9488\u3002\n__cinit__() \u548c __dealloc__() \u65b9\u6cd5\u901a\u8fc7 malloc() \u548c free() \u521b\u5efa\u5e76\u9500\u6bc1\u5e95\u5c42C\u7ed3\u6784\u4f53\u3002\nx\u548cy\u5c5e\u6027\u7684\u58f0\u660e\u8ba9\u4f60\u83b7\u53d6\u548c\u8bbe\u7f6e\u5e95\u5c42\u7ed3\u6784\u4f53\u7684\u5c5e\u6027\u503c\u3002\ndistance() \u7684\u5305\u88c5\u5668\u8fd8\u53ef\u4ee5\u88ab\u4fee\u6539\uff0c\u4f7f\u5f97\u5b83\u80fd\u63a5\u53d7 Point \u6269\u5c55\u7c7b\u578b\u5b9e\u4f8b\u4f5c\u4e3a\u53c2\u6570\uff0c\n\u800c\u4f20\u9012\u5e95\u5c42\u6307\u9488\u7ed9C\u51fd\u6570\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u505a\u4e86\u8fd9\u4e2a\u6539\u53d8\u540e\uff0c\u4f60\u4f1a\u53d1\u73b0\u64cd\u4f5cPoint\u5bf9\u8c61\u5c31\u663e\u5f97\u66f4\u52a0\u81ea\u7136\u4e86\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import sample\np1 = sample.Point(2,3)\np2 = sample.Point(4,5)\np1"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "p2"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "p1.x"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "p1.y"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "sample.distance(p1,p2)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u672c\u8282\u5df2\u7ecf\u6f14\u793a\u4e86\u5f88\u591aCython\u7684\u6838\u5fc3\u7279\u6027\uff0c\u4f60\u53ef\u4ee5\u4ee5\u6b64\u4e3a\u57fa\u51c6\u6765\u6784\u5efa\u66f4\u591a\u66f4\u9ad8\u7ea7\u7684\u5305\u88c5\u3002\n\u4e0d\u8fc7\uff0c\u4f60\u6700\u597d\u5148\u53bb\u9605\u8bfb\u4e0b\u5b98\u65b9\u6587\u6863\u6765\u4e86\u89e3\u66f4\u591a\u4fe1\u606f\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u63a5\u4e0b\u6765\u51e0\u8282\u8fd8\u4f1a\u7ee7\u7eed\u6f14\u793a\u4e00\u4e9bCython\u7684\u5176\u4ed6\u7279\u6027\u3002"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.7.1"
    },
    "toc": {
      "base_numbering": 1,
      "nav_menu": {},
      "number_sections": true,
      "sideBar": true,
      "skip_h1_title": true,
      "title_cell": "Table of Contents",
      "title_sidebar": "Contents",
      "toc_cell": false,
      "toc_position": {},
      "toc_section_display": true,
      "toc_window_display": true
    }
  },
  "nbformat": 4,
  "nbformat_minor": 2
}